<?php
class Model_User extends Forum_Db_Table
{
    protected $_name = 'user';
    
    protected $_primary = 'id';
    
    /**
     * Create a new user
     * 
     * @param array $data
     * @return bool
     */
    public function save($data)
    {
        if (!$this->validateRegister($data)) {
            return false;
        }
        
        $date = date('Y-m-d H:i:s');
        
        $data['password'] = md5($data['password']);
        
        $data = array_merge($data, array(
            'registered_on' => $date,
            'last_login_on' => $date,
            'last_activity_on' => $date,
            'is_admin' => 0,
            'status' => 'disabled'
        ));
                
        $user_id = $this->getAdapter()->insert($this->_name, $data);
        
        Forum_Message::getInstance()->addSuccess("Профіль успішно створено")
            ->addSuccess("Тепер необхідно активувати його");
            
        $this->sendActivationCode($data['email'], 'register');
            
        return true;
    }
    
    /**
     * Create and send activation code
     * 
     * @param string $email
     * @return bool
     */
    public function sendActivationCode($email, $code_type)
    {
        $activation_model = Forum::getSingleton('user/ActivationCode');
        
        $user = $this->getAdapter()->fetchRow("SELECT * FROM user WHERE email = '{$email}'");
        
        if (!$user) {
            Forum_Message::getInstance()->addError("Профілю із вказаною електронною адресою не знайдено");
            return false;
        }
        if ($user['status'] == 'blocked') {
            Forum_Message::getInstance()->addError("Вказаний профіль заблокований адміністрацією");
            return false;
        }
        if ($user['status'] != 'disabled') {
            Forum_Message::getInstance()->addError("Вказаний профіль не потребує активації");
            return false;
        }
        
        $this->getAdapter()->delete('user_activation_code', array(
            "type = '{$code_type}'",
            "user_id = '{$user['id']}'"
        ));
        
        $code_id = $activation_model->create($user['id'], $code_type);
        $code_row = $activation_model->find($code_id);
        
        $link = Forum_Helper_Url::getInstance()->getUrl('account/activate');
        $link .= "?username={$user['username']}&code={$code_row['code']}";
        
        try {
            $mail = new Forum_Mail();
            $mail->setSubject('Форум. Активація акаунта')
                ->setFrom('forum@step.com') //@todo get from config
                ->setBody("Для активації акаунта перейдіть по посиланню: {$link}")
                ->addRecipient($email)
                ->send();
                
            $activation_model->setStatus($code_id, 'sended');
            Forum_Message::getInstance()->addSuccess("Код активації був надісланий на вашу пошту");
        } catch (Exception $e) {
            $activation_url = Forum_Helper_Url::getInstance()->getUrl('account/activate');
            Forum_Message::getInstance()->addError(
                "Код активації не був надісланий. 
                Ви можете спробувати відіслати його ще раз тут:
                <a href='{$activation_url}' title='{$activation_url}'>{$activation_url}</a>"
            );
            $activation_model->setStatus($code_id, 'error');
            return false;
        }
        return true;
    }
    
    /**
     * Activates account after registration
     * 
     * @return bool
     */
    public function activate($data)
    {
        if (!$user_id = $this->getIdByUsername($data['username'])) {
            Forum_Message::getInstance()->addError('Користувача не знайдено');
            return false;
        }
        
        $activationCode = Forum::getSingleton('user/ActivationCode');
        
        if (!$activationCode->validate($user_id, $data['code'])) {
            return false;
        }
        
        $this->getAdapter()->update($this->_name, array('status' => 'enabled'), "id = {$user_id}");
        
        $activationCode->delete($user_id, $data['code']);
        
        Forum_Message::getInstance()->addSuccess('Ваш профіль активовано');
        return true;
    }
    
    /**
     * Delete user rows by ids
     * 
     * @param mixed $id
     * @return bool
     */
    public function delete($ids)
    {
        if (!is_array($ids)) {
            $ids = array($ids);
        }
        
        $count = count($ids);
        $ids = implode(',', $ids);
        
        if ($this->getAdapter()->delete($this->_name, "id IN ({$ids})")) {
            Forum_Message::getInstance()->addSuccess(sprintf('%d %s успішно видалено', $count, (
                $count > 4 ? 'профілів' : (
                    $count > 1 ? 'профіля' : 'профіль' //this is wrong, and i know this :/
                )
            )));
            return true;
        } else {
            Forum_Message::getInstance()->addError('Записи не були видалені. Спробуйте ще раз');
            return false;
        }
    }
    
    /**
     * Validates user data before create new account
     * 
     * @param $data
     * @return bool
     */
    public function validateRegister($data)
    {
        $is_valid = true;
        
        if (!is_array($data)) {
            Forum_Message::getInstance()->addError('Помилка при передачі даних. Спробуйте ще раз');
            return false;
        }
        
        if (!isset($data['username']) || empty($data['username'])) {
            Forum_Message::getInstance()->addError('Ім\'я користувача є обов\'язковим полем');
            $is_valid = false;
        } elseif (strstr($data['username'], '@')) {
            Forum_Message::getInstance()->addError('@ - заборонений символ');
            $is_valid = false;
        } elseif ($this->hasDuplicate('username', $data['username'])) {
            Forum_Message::getInstance()->addError('Дане ім\'я вже використувується');
            $is_valid = false;
        }
        
        if (!isset($data['email']) || empty($data['email'])) {
            Forum_Message::getInstance()->addError('Адреса електронної пошти є обов\'язковим полем');
            $is_valid = false;
        } elseif (!preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9._-]+)+$/", $data['email'])) {
            Forum_Message::getInstance()->addError('Адреса електронної пошти невірна');
            $is_valid = false;
        } elseif ($this->hasDuplicate('email', $data['email'])) {
            Forum_Message::getInstance()->addError('Дана адреса електронної пошти вже використовується');
            $is_valid = false;
        }
        
        if (!isset($data['password']) || empty($data['password'])) {
            Forum_Message::getInstance()->addError('Пароль є обов\'язковим полем');
            $is_valid = false;
        }
        
        return $is_valid;
    }
    
    /**
     * Validates data before user login
     * 
     * @param array $data
     * @return bool
     */
    public function validateLogin($data)
    {
        $is_valid = true;
        
        if (!is_array($data)) {
            Forum_Message::getInstance()->addError('Помилка при передачі даних. Спробуйте ще раз');
            return false;
        }
        
        if (!isset($data['username']) || empty($data['username'])) {
            Forum_Message::getInstance()->addError('Ім\'я користувача є обов\'язковим полем');
            $is_valid = false;
        }
        
        if (!isset($data['password']) || empty($data['password'])) {
            Forum_Message::getInstance()->addError('Пароль є обов\'язковим полем');
            $is_valid = false;
        }
        
        if (!$is_valid) {
            return false;
        }
        
        if (!$row = $this->getUserByEmailOrName($data['username'])) {
            Forum_Message::getInstance()->addError('Користувача не знайдено');
            return false;
        }
        
        if ($row['status'] == 'blocked') {
            Forum_Message::getInstance()->addError('Ваш профіль був заблокований адміністрацією');
            return false;
        }
        
        if ($row['status'] == 'disabled') {
            $activation_url = Forum_Helper_Url::getInstance()->getUrl('account/activate');
            Forum_Message::getInstance()->addError('Ваш профіль не пройшов активацію')
                ->addError("Якщо на вашу електронну адресу не прийшов лист із даними для активації, то
                ви можете спробувати відіслати його ще раз тут:
                <a href='{$activation_url}' title='{$activation_url}'>{$activation_url}</a>");
            return false;
        }
                
        if (md5($data['password']) !== $row['password']) {
            Forum_Message::getInstance()->addError('Невірний пароль');
            return false;
        }
        
        return $is_valid;
    }
    
    /**
     * Retrieve user row by email or username
     * 
     * @param string $username
     * @return array
     */
    public function getUserByEmailOrName($username)
    {
        $query = "SELECT *
            FROM user
            WHERE username = '{$username}'
            OR email = '{$username}'";
        
        return $this->getAdapter()->fetchRow($query);
    }
    
    /**
     * Check is data is unique for the column
     * 
     * @param string $field Column name
     * @param string $data Value
     * @return bool
     */
    public function hasDuplicate($field, $data)
    {
        $query = "SELECT {$field}
            FROM {$this->_name}
            WHERE {$field} = '{$data}'";
        
        if ($this->getAdapter()->fetchRow($query)) {
            return true;
        }
        
        return false;
    }

    /**
     * Get list data by list id
     * 
     * @param array $listId Column id
     * @return array
     */
    public function getListById($listId)
    {
    	if( !isset($listId) ){ return ;	}
		
		if(is_array($listId) && count($listId)){
			$list = implode(", ",$listId); 
			
		}elseif(is_numeric($listId)){
			$list = $listId;
		}else{
			return;
		}
        $query = "SELECT *,
					  UNIX_TIMESTAMP(registered_on) as registered_on,
					  UNIX_TIMESTAMP(last_login_on) as last_login_on,
					  UNIX_TIMESTAMP(last_activity_on) as last_activity_on
            FROM {$this->_name}
            WHERE id in ({$list})";  
        return  $this->getAdapter()->fetchAll($query);

        return false;
    }
    
    /**
     * Retrieve user_id from session.
     * If user not logged in - returns boolean false
     * 
     * @return mixed
     */
    public static function getUserId()
    {
        if (!isset($_SESSION['user_id']))
            return false;
        
        return $_SESSION['user_id'];
    }
    
    /**
     * Retrieve user is_admin flag
     * 
     * @return bool
     */
    public static function isAdmin()
    {
        if (!isset($_SESSION['is_admin']))
            return false;
        
        return $_SESSION['is_admin'];
    }
    
    /**
     * Retrieve list of users
     * 
     * @return array
     */
    public function getList($mode = 'all')
    {
        $query = "SELECT *
            FROM {$this->_name}";
        
        if ($mode != 'all') {
            $query .= " WHERE status = '{$mode}'";
        }
        
        return  $this->getAdapter()->fetchAll($query);
    }
    
    /**
     * Updates user row according to $bind param
     * 
     * @param mixed $user_ids
     * @param array $bind Column => Value pairs
     * @return bool
     */
    public function update($ids, $bind, $quiet = false)
    {
        if (!is_array($ids)) {
            $ids = array($ids);
        }
        
        $count = count($ids);
        $ids = implode(',', $ids);
        
        if ($this->getAdapter()->update($this->_name, $bind, array("id IN ({$ids})"))) {
            if ($quiet == false) {
                Forum_Message::getInstance()->addSuccess(sprintf('%d %s успішно оновлено', $count, (
                    $count > 4 ? 'профілів' : (
                        $count > 1 ? 'профіля' : 'профіль' //this is wrong, and i know this :/
                    )
                )));
            }
            return true;
        } else {
            if ($quiet == false) {
                Forum_Message::getInstance()->addError('Записи не були оновлені. Спробуйте ще раз');
            }
            return false;
        }
    }
    
    public function validatePasswordChange($data)
    {
        $is_valid = true;
        
        if (!isset($data['old']) || empty($data['old'])) {
            Forum_Message::getInstance()->addError('Вкажіть свій старий пароль');
            $is_valid = false;
        }
        
        if (!isset($data['new']) || empty($data['new'])) {
            Forum_Message::getInstance()->addError('Вкажіть новий пароль');
            $is_valid = false;
        }
        
        if (!isset($data['new_confirmation'])) {
            Forum_Message::getInstance()->addError('Підтвердіть новий пароль');
            $is_valid = false;
        }
        
        if ($data['new'] != $data['new_confirmation']) {
            Forum_Message::getInstance()->addError('Невірне підтвердження нового паролю');
            $is_valid = false;
        }
        
        if (!$is_valid) {
            return false;
        }
        
        $user = $this->find(self::getUserId());
        
        if (md5($data['old']) != $user['password']) {
            Forum_Message::getInstance()->addError('Старий пароль є невірним');
            return false;
        }
        
        return true;
    }
    
}